
//  Software Guide : BeginLatex
//
//  This example illustrates how to read a DICOM series into a volume and then
//  save this volume into another DICOM series using the exact same header
//  information. It makes use of the GDCM library.
//
//  The main purpose of this example is to show how to properly propagate the
//  DICOM specific information along the pipeline to be able to correctly write
//  back the image using the information from the input DICOM files.
//
//  Please note that writing DICOM files is quite a delicate operation since we
//  are dealing with a significant amount of patient specific data. It is your
//  responsibility to verify that the DICOM headers generated from this code
//  are not introducing risks in the diagnosis or treatment of patients. It is
//  as well your responsibility to make sure that the privacy of the patient is
//  respected when you process data sets that contain personal information.
//  Privacy issues are regulated in the United States by the HIPAA
//  norms\footnote{The Health Insurance Portability and Accountability Act of
//  1996. \url{http://www.cms.hhs.gov/hipaa/}}. You would probably find similar
//  legislation in every country.
//
//  \index{HIPAA!Privacy}
//  \index{HIPAA!Dicom}
//  \index{Dicom!HIPPA}
//
//  When saving datasets in DICOM format it must be made clear whether this
//  datasets have been processed in any way, and if so, you should inform the
//  recipients of the data about the purpose and potential consequences of the
//  processing. This is fundamental if the datasets are intended to be used for
//  diagnosis, treatment or follow-up of patients. For example, the simple
//  reduction of a dataset form a 16-bits/pixel to a 8-bits/pixel
//  representation may make impossible to detect certain pathologies and as a
//  result will expose the patient to the risk or remaining untreated for a
//  long period of time while her/his pathology progresses.
//
//  You are strongly encouraged to get familiar with the report on medical
//  errors ``To Err is Human'', produced by the U.S. Institute of
//  Medicine~\cite{ToErrIsHuman2001}. Raising awareness about the high
//  frequency of medical errors is a first step in reducing their occurrence.
//
//  \index{Medical Errors}
//
//  Software Guide : EndLatex
// Software Guide : BeginLatex
//
// After all these warnings, let us now go back to the code and get familiar
// with the use of ITK and GDCM for writing DICOM Series. The first step that
// we must take is to include the header files of the relevant classes. We
// include the GDCM image IO class, the GDCM filenames generator, the series
// reader and writer.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
#include "itkGDCMImageIO.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkImageSeriesReader.h"
#include "itkImageSeriesWriter.h"
// Software Guide : EndCodeSnippet
#include <vector>
#include "itksys/SystemTools.hxx"

#include <itkImageToVTKImageFilter.h>
#include <iostream>

// some standard vtk headers
#include <vtkSmartPointer.h>
#include <vtkObjectFactory.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkActor.h>
// headers needed for this example
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
#include <vtkInteractorStyleImage.h>
#include <vtkActor2D.h>
#include <vtkTextProperty.h>
#include <vtkTextMapper.h>
// needed to easily convert int to std::string
#include <sstream>


//Binarizacion por nivel
#include "itkBinaryThresholdImageFilter.h"

//Operaciones morfologicas
#include "itkBinaryMorphologicalClosingImageFilter.h"
#include "itkBinaryBallStructuringElement.h"
#include "itkSubtractImageFilter.h"

//Filtro itk vtk
#include "itkImageToVTKImageFilter.h"

//Diccionario metadata
#include "itkMetaDataObject.h"


//Basicas
#include <stdlib.h>

using namespace std;





// helper class to format slice status message
class StatusMessage {
public:
   static std::string Format(int slice, int maxSlice) {
      std::stringstream tmp;
      tmp << "Slice Number  " << slice + 1 << "/" << maxSlice + 1;
      return tmp.str();
   }
};
 
 
// Define own interaction style
class myVtkInteractorStyleImage : public vtkInteractorStyleImage
{
public:
   static myVtkInteractorStyleImage* New();
   vtkTypeMacro(myVtkInteractorStyleImage, vtkInteractorStyleImage);
 
protected:
   vtkImageViewer2* _ImageViewer;
   vtkTextMapper* _StatusMapper;
   int _Slice;
   int _MinSlice;
   int _MaxSlice;
 
public:
   void SetImageViewer(vtkImageViewer2* imageViewer) {
      _ImageViewer = imageViewer;
      _MinSlice = imageViewer->GetSliceMin();
      _MaxSlice = imageViewer->GetSliceMax();
      _Slice = _MinSlice;
      cout << "Slicer: Min = " << _MinSlice << ", Max = " << _MaxSlice << std::endl;
   }
 
   void SetStatusMapper(vtkTextMapper* statusMapper) {
      _StatusMapper = statusMapper;
   }
 
 
protected:
   void MoveSliceForward() {
      if(_Slice < _MaxSlice) {
         _Slice += 1;
         cout << "MoveSliceForward::Slice = " << _Slice << std::endl;
         _ImageViewer->SetSlice(_Slice);
         std::string msg = StatusMessage::Format(_Slice, _MaxSlice);
         _StatusMapper->SetInput(msg.c_str());
         _ImageViewer->Render();
      }
   }
 
   void MoveSliceBackward() {
      if(_Slice > _MinSlice) {
         _Slice -= 1;
         cout << "MoveSliceBackward::Slice = " << _Slice << std::endl;
         _ImageViewer->SetSlice(_Slice);
         std::string msg = StatusMessage::Format(_Slice, _MaxSlice);
         _StatusMapper->SetInput(msg.c_str());
         _ImageViewer->Render();
      }
   }
 
 
   virtual void OnKeyDown() {
      std::string key = this->GetInteractor()->GetKeySym();
      if(key.compare("Up") == 0) {
         //cout << "Up arrow key was pressed." << endl;
         MoveSliceForward();
      }
      else if(key.compare("Down") == 0) {
         //cout << "Down arrow key was pressed." << endl;
         MoveSliceBackward();
      }
      // forward event
      vtkInteractorStyleImage::OnKeyDown();
   }
 
 
   virtual void OnMouseWheelForward() {
      //std::cout << "Scrolled mouse wheel forward." << std::endl;
      MoveSliceForward();
      // don't forward events, otherwise the image will be zoomed 
      // in case another interactorstyle is used (e.g. trackballstyle, ...)
      // vtkInteractorStyleImage::OnMouseWheelForward();
   }
 
 
   virtual void OnMouseWheelBackward() {
      //std::cout << "Scrolled mouse wheel backward." << std::endl;
      if(_Slice > _MinSlice) {
         MoveSliceBackward();
      }
      // don't forward events, otherwise the image will be zoomed 
      // in case another interactorstyle is used (e.g. trackballstyle, ...)
      // vtkInteractorStyleImage::OnMouseWheelBackward();
   }
};
 
vtkStandardNewMacro(myVtkInteractorStyleImage);

//Funciones
void UmbralizacionNivel(signed short lower, signed short upper);
void leerImagenes(string folder,string folder2);
void leerEncabezado (string nombre,string tag);
double obtenerValorDePixel(string nombreDir);
double obtenerValorDePixel(itk::GDCMImageIO::Pointer dicomIO);
	
	
	
	
	

int main( int argc, char* argv[] )
{
  if( argc < 3 )
    {
    std::cerr << "Usage: " << argv[0] <<
      " DicomDirectory  OutputDicomDirectory" << std::endl;
    return EXIT_FAILURE;
    }
  //  Software Guide : BeginLatex
  //
  //  As a second step, we define the image type to be used in this example. This
  //  is done by explicitly selecting a pixel type and a dimension. Using the
  //  image type we can define the type of the series reader.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  typedef signed short    PixelType;
  const unsigned int      Dimension = 3;
  typedef itk::Image< PixelType, Dimension >      ImageType;
  typedef itk::ImageSeriesReader< ImageType >     ReaderType;
  

  
  
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  //  We also declare types for the \doxygen{GDCMImageIO} object that will
  //  actually read and write the DICOM images, and the
  //  \doxygen{GDCMSeriesFileNames} object that will generate and order all the
  //  filenames for the slices composing the volume dataset. Once we have the
  //  types, we proceed to create instances of both objects.
  //
  // Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  typedef itk::GDCMImageIO                        ImageIOType;
  typedef itk::GDCMSeriesFileNames                NamesGeneratorType;
  ImageIOType::Pointer gdcmIO = ImageIOType::New();
  NamesGeneratorType::Pointer namesGenerator = NamesGeneratorType::New();
  
  
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  //  Just as the previous example, we get the DICOM filenames from the
  //  directory. Note however, that in this case we use the
  //  \code{SetInputDirectory()} method instead of the \code{SetDirectory()}.
  //  This is done because in the present case we will use the filenames
  //  generator for producing both the filenames for reading and the filenames
  //  for writing. Then, we invoke the \code{GetInputFileNames()} method in order
  //  to get the list of filenames to read.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  namesGenerator->SetInputDirectory( argv[1] );
  const ReaderType::FileNamesContainer & filenames =
                            namesGenerator->GetInputFileNames();
  // Software Guide : EndCodeSnippet
  unsigned int numberOfFilenames =  filenames.size();
  std::cout << numberOfFilenames << std::endl;
  for(unsigned int fni = 0; fni<numberOfFilenames; fni++)
    {
    //std::cout << "filename # " << fni << " = ";
    //std::cout << filenames[fni] << std::endl;
    }
  // Software Guide : BeginLatex
  //
  // We construct one instance of the series reader object. Set the DICOM image
  // IO object to be use with it, and set the list of filenames to read.
  //
  // Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetImageIO( gdcmIO );
  reader->SetFileNames( filenames );
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We can trigger the reading process by calling the \code{Update()} method on
  // the series reader. It is wise to put this invocation inside a
  // \code{try/catch} block since the process may eventually throw exceptions.
  //
  // Software Guide : EndLatex
  try
    {
    // Software Guide : BeginCodeSnippet
    reader->Update();
    // Software Guide : EndCodeSnippet
    }
  catch (itk::ExceptionObject &excp)
    {
    std::cerr << "Exception thrown while writing the image" << std::endl;
    std::cerr << excp << std::endl;
    return EXIT_FAILURE;
    }
  // Software Guide : BeginLatex
  //
  // At this point we would have the volumetric data loaded in memory and we can
  // get access to it by invoking the \code{GetOutput()} method in the reader.
  //
  
  
  
    double tamPixel = obtenerValorDePixel(gdcmIO);
	cout<<" valor del pixel  : "<<tamPixel<<endl;
  
  
  
  
  //Binarizacion por nivel
  
  signed short lowerThreshold = -1000;
  signed short upperThreshold = -500;
  
  typedef itk::BinaryThresholdImageFilter <ImageType, ImageType> 
    BinaryThresholdImageFilterType;
  
  BinaryThresholdImageFilterType::Pointer thresholdFilter
    = BinaryThresholdImageFilterType::New();
  
  thresholdFilter->SetInput(reader->GetOutput());
  thresholdFilter->SetLowerThreshold(lowerThreshold);
  thresholdFilter->SetUpperThreshold(upperThreshold);
  //thresholdFilter->SetInsideValue(255);
  //thresholdFilter->SetOutsideValue(0);
  cout<<"se hizo la umbralizacion por nivel"<<endl;
  
  
  //Closing
  double radius = (double)1.2/tamPixel;
  cout<<"radio de : "<<radius<<endl;
  typedef itk::BinaryBallStructuringElement<ImageType::PixelType, ImageType::ImageDimension>
              StructuringElementType;
  StructuringElementType structuringElement;
  structuringElement.SetRadius(radius);
  structuringElement.CreateStructuringElement();
  
  typedef itk::BinaryMorphologicalClosingImageFilter <ImageType, ImageType, StructuringElementType>
          BinaryMorphologicalClosingImageFilterType;
  BinaryMorphologicalClosingImageFilterType::Pointer closingFilter
          = BinaryMorphologicalClosingImageFilterType::New();
  closingFilter->SetInput(thresholdFilter->GetOutput() );
  closingFilter->SetKernel(structuringElement);
  closingFilter->Update();

 
  /*
  typedef itk::SubtractImageFilter<ImageType> SubtractType;
  SubtractType::Pointer diff = SubtractType::New();
  diff->SetInput1(closingFilter->GetOutput());
  diff->SetInput2(reader->GetOutput());
  */
  //cout<<"se hizo el closing"<<endl;
  
  
  
  /*
    //Filtro de VTK
	ImageType::Pointer image=closingFilter->GetOutput();
  
  
  
   vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
    vtkSmartPointer<vtkRenderer> ren1 = vtkSmartPointer<vtkRenderer>::New();
    ren1->SetBackground(0.5f,0.5f,1.0f);
	
	renWin->AddRenderer(ren1);
    renWin->SetSize(1280,1024);
    vtkSmartPointer<vtkRenderWindowInteractor> iren = 
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    iren->SetRenderWindow(renWin);
    renWin->Render(); // make sure we have an OpenGL context.
	
	    typedef itk::ImageToVTKImageFilter<ImageType> itkVtkConverter;
    itkVtkConverter::Pointer conv=itkVtkConverter::New();
    conv->SetInput(image);
    conv->Update();
	
	renWin->Render();
	iren->Start();
	*/
  /*
  vtkSmartPointer<vtkImageActor> actor =
    vtkSmartPointer<vtkImageActor>::New();
	#if VTK_MAJOR_VERSION <= 5
	actor->SetInput(connector->GetOutput());
	#else
	connector->Update();
	actor->GetMapper()->SetInputData(connector->GetOutput());
	#endif
  */
  
  
  

  
  
  
  
  // Software Guide : EndLatex
  //  Software Guide : BeginLatex
  //
  //  Now we can prepare the process for writing the dataset. First, we take the
  //  name of the output directory from the command line arguments.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  const char * outputDirectory = argv[2];
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  //  Second, we make sure the output directory exist, using the cross platform
  //  tools: itksys::SystemTools. In this case we select to create the directory
  //  if it does not exist yet.
  //
  //  \index{itksys!SystemTools}
  //  \index{itksys!MakeDirectory}
  //  \index{SystemTools}
  //  \index{SystemTools!MakeDirectory}
  //  \index{MakeDirectory!SystemTools}
  //  \index{MakeDirectory!itksys}
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  itksys::SystemTools::MakeDirectory( outputDirectory );
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We instantiate explicitly the image type to be used for writing, and use the
  // image type for instantiating the type of the series writer.
  //
  // Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  typedef signed short    OutputPixelType;
  const unsigned int      OutputDimension = 2;
  typedef itk::Image< OutputPixelType, OutputDimension >    Image2DType;
  typedef itk::ImageSeriesWriter<ImageType, Image2DType >  SeriesWriterType;
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  //  We construct a series writer and connect to its input the output from the
  //  reader. Then we pass the GDCM image IO object in order to be able to write
  //  the images in DICOM format.
  //
  //  the writer filter.  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();
  
  
  
  
  
  //seriesWriter->SetInput( closingFilter->GetOutput() );
  
  
  seriesWriter->SetInput( closingFilter->GetOutput() );
  
  
  
  
  
  seriesWriter->SetImageIO( gdcmIO );
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  //  It is time now to setup the GDCMSeriesFileNames to generate new filenames
  //  using another output directory.  Then simply pass those newly generated
  //  files to the series writer.
  //
  //  \index{GDCMSeriesFileNames!SetOutputDirectory()}
  //  \index{GDCMSeriesFileNames!GetOutputFileNames()}
  //  \index{ImageSeriesWriter!SetFileNames()}
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  namesGenerator->SetOutputDirectory( outputDirectory );
  seriesWriter->SetFileNames( namesGenerator->GetOutputFileNames() );
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  //  The following line of code is extremely important for this process to work
  //  correctly.  The line is taking the MetaDataDictionary from the input reader
  //  and passing it to the output writer. The reason why this step is so
  //  important is that the MetaDataDictionary contains all the entries of the
  //  input DICOM header.
  //
  //  \index{itk::ImageSeriesReader!GetMetaDataDictionaryArray()}
  //  \index{itk::ImageSeriesWriter!SetMetaDataDictionaryArray()}
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  seriesWriter->SetMetaDataDictionaryArray(reader->GetMetaDataDictionaryArray() );
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // Finally we trigger the writing process by invoking the \code{Update()} method
  // in the series writer. We place this call inside a try/catch block, in case
  // any exception is thrown during the writing process.
  //
  // Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  try
    {
    seriesWriter->Update();
    }
  catch( itk::ExceptionObject & excp )
    {
    std::cerr << "Exception thrown while writing the series " << std::endl;
    std::cerr << excp << std::endl;
    return EXIT_FAILURE;
    }
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // Please keep in mind that you should avoid to generate DICOM files that have
  // the appearance of being produced by a scanner. It should be clear from the
  // directory or filenames that this data was the result of the
  // execution of some sort of algorithm. This will help to prevent your dataset
  // from being used as scanner data by accident.
  //
  // Software Guide : EndLatex
  
	const char * inputDirectory = argv[1];
	leerImagenes(inputDirectory,outputDirectory);
  return EXIT_SUCCESS;
}
/*
Tarballs of the nightly generated Doxygen documentation are available for the html, xml, and tag file.
Generated on Mon May 12 2014 01:40:36 for ITK by   doxygen 1.8.5
*/

void leerImagenes(string folder, string folder2){
	
	//Entrada
   vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
   reader->SetDirectoryName(folder.c_str());
   reader->Update();
 
   // Visualize
   vtkSmartPointer<vtkImageViewer2> imageViewer = vtkSmartPointer<vtkImageViewer2>::New();
   imageViewer->SetInputConnection(reader->GetOutputPort());
 
   // slice status message
   vtkSmartPointer<vtkTextProperty> sliceTextProp = vtkSmartPointer<vtkTextProperty>::New();
   sliceTextProp->SetFontFamilyToCourier();
   sliceTextProp->SetFontSize(20);
   sliceTextProp->SetVerticalJustificationToBottom();
   sliceTextProp->SetJustificationToLeft();
 
   vtkSmartPointer<vtkTextMapper> sliceTextMapper = vtkSmartPointer<vtkTextMapper>::New();
   std::string msg = StatusMessage::Format(imageViewer->GetSliceMin(), imageViewer->GetSliceMax());
   sliceTextMapper->SetInput(msg.c_str());
   sliceTextMapper->SetTextProperty(sliceTextProp);
 
   vtkSmartPointer<vtkActor2D> sliceTextActor = vtkSmartPointer<vtkActor2D>::New();
   sliceTextActor->SetMapper(sliceTextMapper);
   sliceTextActor->SetPosition(15, 10);
 
   // usage hint message
   vtkSmartPointer<vtkTextProperty> usageTextProp = vtkSmartPointer<vtkTextProperty>::New();
   usageTextProp->SetFontFamilyToCourier();
   usageTextProp->SetFontSize(14);
   usageTextProp->SetVerticalJustificationToTop();
   usageTextProp->SetJustificationToLeft();
 
   vtkSmartPointer<vtkTextMapper> usageTextMapper = vtkSmartPointer<vtkTextMapper>::New();
   //usageTextMapper->SetInput("- Slice with mouse wheel\n  or Up/Down-Key\n- Zoom with pressed right\n  mouse button while dragging");
    usageTextMapper->SetInput("Entrada");
   usageTextMapper->SetTextProperty(usageTextProp);
 
   vtkSmartPointer<vtkActor2D> usageTextActor = vtkSmartPointer<vtkActor2D>::New();
   usageTextActor->SetMapper(usageTextMapper);
   usageTextActor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
   usageTextActor->GetPositionCoordinate()->SetValue( 0.05, 0.95);
 
   // create an interactor with our own style (inherit from vtkInteractorStyleImage)
   // in order to catch mousewheel and key events
   vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
 
   vtkSmartPointer<myVtkInteractorStyleImage> myInteractorStyle = vtkSmartPointer<myVtkInteractorStyleImage>::New();
 
   // make imageviewer2 and sliceTextMapper visible to our interactorstyle
   // to enable slice status message updates when scrolling through the slices
   myInteractorStyle->SetImageViewer(imageViewer);
   myInteractorStyle->SetStatusMapper(sliceTextMapper);
 
   imageViewer->SetupInteractor(renderWindowInteractor);
   // make the interactor use our own interactorstyle
   // cause SetupInteractor() is defining it's own default interatorstyle 
   // this must be called after SetupInteractor()
   renderWindowInteractor->SetInteractorStyle(myInteractorStyle);
   // add slice status message and usage hint message to the renderer
   imageViewer->GetRenderer()->AddActor2D(sliceTextActor);
   imageViewer->GetRenderer()->AddActor2D(usageTextActor);
 
   // initialize rendering and interaction
   //imageViewer->GetRenderWindow()->SetSize(400, 300);
   //imageViewer->GetRenderer()->SetBackground(0.2, 0.3, 0.4);
   imageViewer->Render();
   imageViewer->GetRenderer()->ResetCamera();
   imageViewer->Render();
   

   
   
   //Salida
   vtkSmartPointer<vtkDICOMImageReader> reader2 = vtkSmartPointer<vtkDICOMImageReader>::New();
   reader2->SetDirectoryName(folder2.c_str());
   reader2->Update();
 
   // Visualize
   vtkSmartPointer<vtkImageViewer2> imageViewer2 = vtkSmartPointer<vtkImageViewer2>::New();
   imageViewer2->SetInputConnection(reader2->GetOutputPort());
 
   // slice status message
   vtkSmartPointer<vtkTextProperty> sliceTextProp2 = vtkSmartPointer<vtkTextProperty>::New();
   sliceTextProp2->SetFontFamilyToCourier();
   sliceTextProp2->SetFontSize(20);
   sliceTextProp2->SetVerticalJustificationToBottom();
   sliceTextProp2->SetJustificationToLeft();
 
   vtkSmartPointer<vtkTextMapper> sliceTextMapper2 = vtkSmartPointer<vtkTextMapper>::New();
   std::string msg2 = StatusMessage::Format(imageViewer2->GetSliceMin(), imageViewer2->GetSliceMax());
   sliceTextMapper2->SetInput(msg2.c_str());
   sliceTextMapper2->SetTextProperty(sliceTextProp2);
 
   vtkSmartPointer<vtkActor2D> sliceTextActor2 = vtkSmartPointer<vtkActor2D>::New();
   sliceTextActor2->SetMapper(sliceTextMapper2);
   sliceTextActor2->SetPosition(15, 10);
 
   // usage hint message
   vtkSmartPointer<vtkTextProperty> usageTextProp2 = vtkSmartPointer<vtkTextProperty>::New();
   usageTextProp2->SetFontFamilyToCourier();
   usageTextProp2->SetFontSize(14);
   usageTextProp2->SetVerticalJustificationToTop();
   usageTextProp2->SetJustificationToLeft();
 
   vtkSmartPointer<vtkTextMapper> usageTextMapper2 = vtkSmartPointer<vtkTextMapper>::New();
   //usageTextMapper->SetInput("- Slice with mouse wheel\n  or Up/Down-Key\n- Zoom with pressed right\n  mouse button while dragging");
   usageTextMapper2->SetInput("Salida");
   usageTextMapper2->SetTextProperty(usageTextProp2);
 
   vtkSmartPointer<vtkActor2D> usageTextActor2 = vtkSmartPointer<vtkActor2D>::New();
   usageTextActor2->SetMapper(usageTextMapper2);
   usageTextActor2->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
   usageTextActor2->GetPositionCoordinate()->SetValue( 0.05, 0.95);
 
   // create an interactor with our own style (inherit from vtkInteractorStyleImage)
   // in order to catch mousewheel and key events
   vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor2 = vtkSmartPointer<vtkRenderWindowInteractor>::New();
 
   vtkSmartPointer<myVtkInteractorStyleImage> myInteractorStyle2 = vtkSmartPointer<myVtkInteractorStyleImage>::New();
 
   // make imageviewer2 and sliceTextMapper visible to our interactorstyle
   // to enable slice status message updates when scrolling through the slices
   myInteractorStyle2->SetImageViewer(imageViewer2);
   myInteractorStyle2->SetStatusMapper(sliceTextMapper2);
 
   imageViewer2->SetupInteractor(renderWindowInteractor2);
   // make the interactor use our own interactorstyle
   // cause SetupInteractor() is defining it's own default interatorstyle 
   // this must be called after SetupInteractor()
   renderWindowInteractor2->SetInteractorStyle(myInteractorStyle2);
   // add slice status message and usage hint message to the renderer
   imageViewer2->GetRenderer()->AddActor2D(sliceTextActor2);
   imageViewer2->GetRenderer()->AddActor2D(usageTextActor2);
 
   // initialize rendering and interaction
   //imageViewer->GetRenderWindow()->SetSize(400, 300);
   //imageViewer->GetRenderer()->SetBackground(0.2, 0.3, 0.4);
   imageViewer2->Render();
   imageViewer2->GetRenderer()->ResetCamera();
   imageViewer2->Render();
      
   renderWindowInteractor->Start();
   renderWindowInteractor2->Start();
}

void UmbralizacionNivel(signed short lower, signed short upper){
	cout<<"funcion"<<endl;
}

void leerEncabezado (string nombre,string tagAux){
	
	typedef signed short       PixelType;
	const unsigned int         Dimension = 3;
		
	typedef itk::Image< PixelType, Dimension >      ImageType;
	typedef itk::ImageSeriesReader< ImageType >     ReaderType;
	
	ReaderType::Pointer reader = ReaderType::New();
	
	typedef itk::GDCMImageIO       ImageIOType;
	ImageIOType::Pointer dicomIO = ImageIOType::New();
	
	reader->SetImageIO( dicomIO );
		
	typedef itk::GDCMSeriesFileNames     NamesGeneratorType;
	NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();
	nameGenerator->SetInputDirectory(nombre);
	
	typedef std::vector<std::string>    FileNamesContainer;
	FileNamesContainer fileNames = nameGenerator->GetInputFileNames();
	
	reader->SetFileNames( fileNames );
	
	try
    {
		reader->Update();
    }
	catch (itk::ExceptionObject &ex)
    {
		std::cout << ex << std::endl;
		return ;
    }
	
	typedef itk::MetaDataDictionary   DictionaryType;
	const  DictionaryType & dictionary = dicomIO->GetMetaDataDictionary();
	typedef itk::MetaDataObject< std::string > MetaDataStringType;
	
	DictionaryType::ConstIterator itr = dictionary.Begin();
	DictionaryType::ConstIterator end = dictionary.End();
	
	
	cout<<endl<<endl<<"---VALORES DEL METADATA---"<<endl;
	while( itr != end )
    {
		itk::MetaDataObjectBase::Pointer  entry = itr->second;
		MetaDataStringType::Pointer entryvalue =
		  dynamic_cast<MetaDataStringType *>( entry.GetPointer() );
		if( entryvalue )
		  {
			  std::string tagkey   = itr->first;
			  std::string tagvalue = entryvalue->GetMetaDataObjectValue();
			  std::cout << tagkey <<  " = " << tagvalue << std::endl;
		  }
		++itr;
    }
	
	std::string entryId = tagAux;
	
	cout<<endl<<endl<<"Tag de "<<entryId<<endl;
	DictionaryType::ConstIterator tagItr = dictionary.Find( entryId );
	
	if( tagItr == end )
    {
		std::cerr << "Tag " << entryId;
		std::cerr << " not found in the DICOM header" << std::endl;
		return ;
    }
	
	 MetaDataStringType::ConstPointer entryvalue =
    dynamic_cast<const MetaDataStringType *>( tagItr->second.GetPointer() );

	 if( entryvalue )
    {
		std::string tagvalue = entryvalue->GetMetaDataObjectValue();
		std::cout << "Patient's Name (" << entryId <<  ") ";
		std::cout << " is: " << tagvalue << std::endl;
    }
	else
    {
		std::cerr << "Entry was not of string type" << std::endl;
		return;
    }	
}

double obtenerValorDePixel(string nombreDir){
	
	typedef signed short       PixelType;
	const unsigned int         Dimension = 3;
		
	typedef itk::Image< PixelType, Dimension >      ImageType;
	typedef itk::ImageSeriesReader< ImageType >     ReaderType;
	
	ReaderType::Pointer reader = ReaderType::New();
	
	typedef itk::GDCMImageIO       ImageIOType;
	ImageIOType::Pointer dicomIO = ImageIOType::New();
	
	reader->SetImageIO( dicomIO );
		
	typedef itk::GDCMSeriesFileNames     NamesGeneratorType;
	NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();
	nameGenerator->SetInputDirectory(nombreDir);
	
	typedef std::vector<std::string>    FileNamesContainer;
	FileNamesContainer fileNames = nameGenerator->GetInputFileNames();
	
	reader->SetFileNames( fileNames );
	
	try
    {
		reader->Update();
    }
	catch (itk::ExceptionObject &ex)
    {
		std::cout << ex << std::endl;
		return -1;
    }
	
	typedef itk::MetaDataDictionary   DictionaryType;
	const  DictionaryType & dictionary = dicomIO->GetMetaDataDictionary();
	typedef itk::MetaDataObject< std::string > MetaDataStringType;
	
	DictionaryType::ConstIterator itr = dictionary.Begin();
	DictionaryType::ConstIterator end = dictionary.End();
	

	std::string entryId = "0028|0030";
	DictionaryType::ConstIterator tagItr = dictionary.Find( entryId );
	
	if( tagItr == end )
    {
		std::cerr << "Tag " << entryId;
		std::cerr << " not found in the DICOM header" << std::endl;
		return -1;
    }
	
	 MetaDataStringType::ConstPointer entryvalue =
    dynamic_cast<const MetaDataStringType *>( tagItr->second.GetPointer() );

	 if( entryvalue )
    {
		std::string tagvalue = entryvalue->GetMetaDataObjectValue();
		return atof(tagvalue.c_str());
    }
	else
    {
		std::cerr << "Entry was not of string type" << std::endl;
		return -1;
    }
}




double obtenerValorDePixel(itk::GDCMImageIO::Pointer dicomIO){
	
	typedef itk::MetaDataDictionary   DictionaryType;
	const  DictionaryType & dictionary = dicomIO->GetMetaDataDictionary();
	typedef itk::MetaDataObject< std::string > MetaDataStringType;
	
	DictionaryType::ConstIterator itr = dictionary.Begin();
	DictionaryType::ConstIterator end = dictionary.End();
	

	std::string entryId = "0028|0030";
	DictionaryType::ConstIterator tagItr = dictionary.Find( entryId );
	
	if( tagItr == end )
    {
		std::cerr << "Tag " << entryId;
		std::cerr << " not found in the DICOM header" << std::endl;
		return -1;
    }
	
	 MetaDataStringType::ConstPointer entryvalue =
    dynamic_cast<const MetaDataStringType *>( tagItr->second.GetPointer() );

	 if( entryvalue )
    {
		std::string tagvalue = entryvalue->GetMetaDataObjectValue();
		return atof(tagvalue.c_str());
    }
	else
    {
		std::cerr << "Entry was not of string type" << std::endl;
		return -1;
    }
}